/*
 * @Author: saber
 * @Date: 2021-11-02 15:22:44
 * @LastEditTime: 2022-07-14 09:45:55
 * @LastEditors: mayijun
 * @Description:
 */
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
import axios, { AxiosInstance } from 'axios';
import InterceptorManager from 'axios/lib/core/InterceptorManager';
import utils from 'axios/lib/utils';
import mergeConfig from 'axios/lib/core/mergeConfig';
import pkg from 'eventemitter2';
const { EventEmitter2 } = pkg;

export const defalutValidateStatus = (status: number) => {
  // 状态
  return status >= 200 && status < 300;
};

// 默认的配置
const defalutOptions = {
  validateStatus: defalutValidateStatus,
  withCredentials: true, // 跨域设置
  timeout: 500000 // 设置超时
};

// 发布订阅 是否是要内置
// 内置的好处 是可以增加一些中间件 发布消息 的机制， 来让其他的中间件 或者 其他的业务
class SaberHTTP extends EventEmitter2 {
  _axios: AxiosInstance;
  // TODO: 中间件 目前还是用拦截器来实现中间件，后续是否自己来实现中间件呢？如何取消一个中间件呢
  middlewareManager: any[] = []; // 中间件 数组 可以管理 中间件

  // 一些错误的抛出

  constructor(optios = {}) {
    super();
    // 增加代理  调用 _axios 的方法
    this._axios = axios.create({ ...defalutOptions, ...optios });
    // TODO: 添加一个 重置头的方法 ，需要判断传过来的 options 目前先这样吧
    // 修改了一下 post的请求头
    this._axios.defaults.headers.post['Content-Type'] = 'application/json'; // 设置post请求头
  }

  // 默认值

  /**
   *  1. 两种方案
   *  middleware 是一个对象 {
   *    name: '',
   *    requestSuccess,
   *    requestError,
   *    responseSuccess,
   *    responseError
   *  }
   *
   * 2. 另外就是 一个方方法
   * 好处就是可以拿到 当前的axios
   */
  // use(middleware, middlewareConfig) {
  //   this._axios.defaults[middleware.name] = middlewareConfig;
  //   this._axios.interceptors.request.use(middleware.requestSuccess, middleware.requestError)
  //   this._axios.interceptors.response.use((response) => {
  //     return middleware.responseSuccess.call(null, response)
  //   }, middleware.responseError)
  // }

  // 是否已经初始化了拦截器了
  isInitInterceptor = false;

  // use(middleware, middlewareConfig) {
  //  this.isInitInterceptor = false;
  //  this.middlewareManager.unshift({
  //   middleware: middleware,
  //   middlewareConfig
  //  })
  // }

  // 采用的是方法 目前先支持同步方法
  use(fn, middlewareConfig: any = {}) {
    const middleware = fn(this);
    if (!middleware.name) {
      // 报错
      console.error('已经有同名的中间件存在了');
      return;
    }
    this.isInitInterceptor = false;
    this.middlewareManager.unshift({
      middleware: middleware,
      middlewareConfig
    });
  }

  // 初始化一下拦截器
  initInterceptor(config) {
    if (!this.isInitInterceptor) {
      this._axios.interceptors.request = new InterceptorManager();
      this._axios.interceptors.response = new InterceptorManager();
      this.middlewareManager.forEach(({ middleware, middlewareConfig }) => {
        this.interceptorsUse(middleware, middlewareConfig);
      });
    }
    this.isInitInterceptor = true;

  }
  // 拦截器的添加
  interceptorsUse(middleware, middlewareConfig) {
    // eslint-disable-next-line @typescript-eslint/no-this-alias
    const _self = this;
    this._axios.defaults[middleware.name] = middlewareConfig;
    this._axios.interceptors.request.use(
      function (response) {
        return middleware.requestSuccess.call(_self, response);
      },
      function (error) {
        return middleware.requestError.call(_self, error);
      }
    );
    this._axios.interceptors.response.use(
      function (response) {
        return middleware.responseSuccess.call(_self, response);
      },
      function (error) {
        return middleware.responseError.call(_self, error);
      }
    );
  }


  // request 的请求
  request<T = any>(config: AxiosRequestConfig): Promise<T> {

    //url请求增加统一目录，/api除外
    if (config.url.indexOf("/api") == -1) {
      config.url = process.env.VUE_APP_SERVERPATH + config.url;
    }
    // 如何 每一个请求产生隔离呢
    this.initInterceptor(config);

    return this._axios.request(config);
  }
  // 创建一个 中间件的 方法 ？
  static createMiddleware() { }
}

// TODO: 后续会参考修改成 代理
// Provide aliases for supported request methods
utils.forEach(
  ['delete', 'get', 'head', 'options'],
  function forEachMethodNoData(method) {
    /*eslint func-names:0*/
    SaberHTTP.prototype[method] = function (url, config) {
      return this.request(
        mergeConfig(config || {}, {
          method: method,
          url: url,
          data: (config || {}).data,
        })
      );
    };
  }
);

utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) {
  /*eslint func-names:0*/
  SaberHTTP.prototype[method] = function (url, data, config) {
    return this.request(
      mergeConfig(config || {}, {
        method: method,
        url: url,
        data: data
      })
    );
  };
});

export default SaberHTTP;
